package com.aifeng.utils

import android.graphics.Rect
import android.view.View
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.aifeng.common_ui.helper.dp2px

class GridGapDecoration
@JvmOverloads
constructor(
        horizontal: Int = 10,
        vertical: Int = 0
) : RecyclerView.ItemDecoration() {

    private var gapSizeHorizontal = dp2px(horizontal.toFloat())
    private var gapSizeVertical = dp2px(vertical.toFloat())

    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
        super.getItemOffsets(outRect, view, parent, state)
        val position = parent.getChildLayoutPosition(view)
        val adapterPostion = parent.getChildAdapterPosition(view)

        when (parent.layoutManager) {
            is GridLayoutManager -> {
                val manager = parent.layoutManager as GridLayoutManager
                val itemCount = manager.itemCount                                     //item总数
                val spanCount = manager.spanCount                                     //列数
                val sizeLookup = manager.spanSizeLookup //item所占列数管理类
                val spanSize = sizeLookup.getSpanSize(adapterPostion)                 //当前item所占列数

                if (spanCount > 0) {
                    if (spanSize == spanCount) {
                        //item占满一行，不做偏移处理
                        outRect.set(0, 0, 0, 0)
                    } else {
                        val lastFullSpanCountPos = getLastFullSpanCountPostion(sizeLookup, spanCount, adapterPostion)

                        //检查是否位于网格中的最后一列
                        val isLastCol = isLastGridCol(spanCount, position, lastFullSpanCountPos)

                        //这里这样分割主要为了让每个grid当中的item的宽度都是保持一致
                        val right = if (isLastCol) gapSizeHorizontal else 0
                        val left = if (isLastCol) 0 else gapSizeHorizontal

                        //检查是否允许网格中的第一行元素的marginTop是否允许设置值 -true标识允许
                        val top = if (isFristGridRow(spanCount, position, lastFullSpanCountPos)) gapSizeVertical else 0
                        //检查是否允许网格中的最后一行元素的marginBottom是否允许设置值 -true标识允许
                        val bottom: Int = if (isLastGridRow(spanCount, position, itemCount)) gapSizeVertical else 0

                        outRect.set(left, top, right, bottom)
                    }
                }
            }
            else -> throw IllegalAccessError("暂只支持Grid布局")
        }
    }

    //寻找上方最近一个占据spanCount整列的位置
    private fun getLastFullSpanCountPostion(
            sizeLookup: GridLayoutManager.SpanSizeLookup,
            spanCount: Int,
            adapterPostion: Int
    ): Int {
        (adapterPostion downTo 0).forEach {
            if (sizeLookup.getSpanSize(it) == spanCount) return it
        }
        return -1
    }

    //是否为最后一列数据
    private fun isLastGridCol(
            spanCount: Int,
            position: Int,
            lastFullSpanPosition: Int
    ) = (position - lastFullSpanPosition) % spanCount == 0

    //是否为第一行数据
    private fun isFristGridRow(
            spanCount: Int,
            position: Int,
            lastFullSpanPosition: Int
    ) = position - lastFullSpanPosition <= spanCount

    //是否为最后一行数据
    private fun isLastGridRow(
            spanCount: Int,
            position: Int,
            itemCount: Int
    ) = itemCount - position <= spanCount

}
